package com.kgc.sbt.interceptor;

import com.kgc.sbt.config.annotation.RequestPermission;
import com.kgc.sbt.exception.UserException;
import com.kgc.sbt.exception.UserExceptionEnum;
import com.kgc.sbt.util.RedisUtils;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.util.StringUtils;
import org.springframework.web.method.HandlerMethod;
import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.ModelAndView;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

/**
 * Created on 2021/6/22.
 * <p>
 * Author: GongMingJie
 * <p>
 * Description: 权限校验拦截器
 */
@Slf4j
public class SecurityInterceptor implements HandlerInterceptor {

    @Autowired
    private RedisUtils redisUtils;

    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {

        // 判断是否需要做权限校验，如果需要，获取token，不需要，就直接放行
        if (this.checkRequestPermission(handler)){
            // 获取token
            String token = request.getHeader("token");

            // 非空校验
            if(StringUtils.isEmpty(token)){
                log.error("------ token为空，权限不足，请重新登录");
//                throw  new RuntimeException("token为空，权限不足，请重新登录");
                throw new UserException(UserExceptionEnum.TOKEN_NULL_EXCPT);
            }

            // 验证token是否有效
            Object userObj = redisUtils.get(token);
            if(StringUtils.isEmpty(userObj)){
                log.error("------ token非法或者已失效");
//                throw  new RuntimeException("token非法或者已失效");
                throw new UserException(UserExceptionEnum.TOKEN_OUT_EXCPT);
            }

        }

        // 直接放行，权限校验通过，或者不需要校验
        return true;
    }

    @Override
    public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {

    }

    @Override
    public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception e) throws Exception {

    }

    /**
     * Created on 2021/6/17
     * Author: GongMingJie
     * @param
     * @return
     * Description: 目标方法是否加了权限许可注解
     */
    private boolean checkRequestPermission(Object handler){

        // 判断当前handler是否映射了目标处理方法
        if (handler instanceof HandlerMethod){
            // 强转为HandlerMethod对象（封装了目标处理方法）
            HandlerMethod handlerMethod = (HandlerMethod) handler;

            // 获取请求处理方法上有没有加请求许可注解
            RequestPermission requestPermission = handlerMethod.getMethod().getAnnotation(RequestPermission.class);

            // 如果方法上取不到，不代表不需要鉴权，还要看方法所在的类上有没有加注解
            if (requestPermission == null){
                requestPermission = handlerMethod.getMethod().getDeclaringClass().getAnnotation(RequestPermission.class);
            }

            // 如果获取到了注解对象，代表要进行权限校验，否则放行
            if (null != requestPermission){
                return true;
            }
        }
        // 不需要鉴权，放行
        return false;
    }
}
